package cn.dlc.com.config;

import cn.dlc.com.account.service.AccountService;
import cn.dlc.com.log.dao.DuplicationDao;
import cn.dlc.com.log.entity.AccountChangeEvent;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

/**
 * @author 邓立川
 * @date 2021/1/28 14:40
 * @desc 监听消息的发送情况
 */

@Slf4j
@Component
// 注意这个名字和半事务消息指定的一样
@RocketMQTransactionListener(txProducerGroup = "tx_producer_group")
public class AccountServiceListener implements RocketMQLocalTransactionListener {

    @Autowired
    private AccountService accountService;

    @Autowired
    private DuplicationDao duplicationDao;

    /**
     * 消息发送之后执行本地事务，主动执行，消息队列根据执行的结果来处理收到的消息
     * @param message 这个参数可以在发送的时候设置header，然后再这边获取
     * @param o 这个其实就是sendMessageInTransaction方法中的最后一个参数
     * @return
     */
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {

        try {
            // 获取对应的消息
            String result = new String((byte[]) message.getPayload());
            // 转换为对象
            AccountChangeEvent accountChangeEvent = JSON.parseObject(result, AccountChangeEvent.class);
            // 保存数据
            accountService.updateAccountBalance(accountChangeEvent);

            log.info("本地事务提交成功{}",message);

            return RocketMQLocalTransactionState.COMMIT;
        } catch (Exception e) {
            e.printStackTrace();
            log.info("本地事务提交失败{}",message);
            return RocketMQLocalTransactionState.ROLLBACK;
        }
    }

    /**
     * 检查本地事务是否执行了，
     * @param message
     * @return
     */
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message message) {

        // 获取对应的消息
        String result = new String((byte[]) message.getPayload());
        // 转换为对象
        AccountChangeEvent accountChangeEvent = JSON.parseObject(result, AccountChangeEvent.class);

        // 获取到对应的事务日志id
        if(duplicationDao.existsById(accountChangeEvent.getTxNo())) {
            // 如果存在，表示本地事务已经提交了，这个时候需要告诉消息队列提交消息
            return RocketMQLocalTransactionState.COMMIT;
        } else {
            // 没有这个记录，什么也不做
            return RocketMQLocalTransactionState.UNKNOWN;
        }
    }
}
